//------------------------------------------------------------------------------------------------
// The MIT License (MIT)
// 
// Copyright (c) 2019 Crsky
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//------------------------------------------------------------------------------------------------

#include "base_types.h"
#include "host.h"
#include "command_line.h"
#include "convar.h"
#include "command_buffer.h"

//------------------------------------------------------------------------------------------------
// Console variables
//------------------------------------------------------------------------------------------------

ConVar fps_max { "fps_max", 300.0, CONVAR_ENGINE, L"Frame per second" };

//------------------------------------------------------------------------------------------------
// Implementation
//------------------------------------------------------------------------------------------------
class CHost : public IHost
{
public:
	CHost();
	CHost( const CHost& ) = delete;
	CHost& operator=( const CHost& ) = delete;
	~CHost();

public:
	virtual void Frame( double frame_time ) override;

private:
	// Returns false if the time is too short to run a frame
	bool FilterTime( double frame_time );
};

//------------------------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------------------------
CHost::CHost()
{
}

//------------------------------------------------------------------------------------------------
// Destructor
//------------------------------------------------------------------------------------------------
CHost::~CHost()
{
}

//------------------------------------------------------------------------------------------------
// Returns false if the time is too short to run a frame
//------------------------------------------------------------------------------------------------
bool CHost::FilterTime( double frame_time )
{
	double min_interval = 1.0 / fps_max.GetValueDouble();
	return frame_time >= min_interval;
}

//------------------------------------------------------------------------------------------------
// Host frame
//------------------------------------------------------------------------------------------------
void CHost::Frame( double frame_time )
{
	// Limit frames per second
	if ( !FilterTime( frame_time ) )
		return;

	HandleInput();

	// Process console commands
	CommandBuffer()->Execute();

	UpdateClientData();

	if ( Server()->IsActive() )
	{
		Client()->Move();
	}

	// 
	// server operations
	// 

	Server()->Frame();

	// 
	// client operations
	// 

	if ( !Server()->IsActive() )
	{
		Client()->Move();
	}

	Client()->SetLastUpdate();
	Client()->ReadPackets();
	Client()->RedoPrediction();
	Client()->EmitEntities();
	Client()->CheckForResend();
	Client()->MoveSpectatorCamera();

	Screen()->Update();

	Sound()->Update();

	Client()->AdjustClock();
}
